package com.luo.d3s.ext.event.jdbc.repository;

import com.luo.d3s.core.domain.event.DomainEvent;
import com.luo.d3s.core.domain.event.DomainEventRecordRepository;
import com.luo.d3s.ext.event.jdbc.convertor.DomainEventRecordConvertor;
import com.luo.d3s.ext.event.jdbc.dataobject.DomainEventRecordDo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * 领域事件接收记录存储实现
 *
 * @author luohq
 * @date 2022-12-22 13:30
 */
@Component
public class DomainEventRecordRepositoryImpl implements DomainEventRecordRepository {

    private static final Logger log = LoggerFactory.getLogger(DomainEventRecordRepositoryImpl.class);

    private NamedParameterJdbcTemplate npJdbcTemplate;

    public DomainEventRecordRepositoryImpl(NamedParameterJdbcTemplate npJdbcTemplate) {
        this.npJdbcTemplate = npJdbcTemplate;
    }

    @Override
    public Boolean record(DomainEvent event) {
        try {
            String sql = "insert into domain_event_record(event_id, record_time) values(:eventId, :recordTime)";
            DomainEventRecordDo domainEventRecordDo = DomainEventRecordConvertor.toRecordDo(event);
            this.npJdbcTemplate.update(sql, new BeanPropertySqlParameterSource(domainEventRecordDo));
            return true;
        } catch (DuplicateKeyException dke) {
            log.warn("Domain event {}.{} is already consumed, skip it.", event.getClass().getSimpleName(), event.getEventId());
            return false;
        } catch (Throwable t) {
            log.warn("Error while record {}.", event.getEventId());
            return false;
        }
    }

    @Override
    public void deleteBeforeDays(Integer retentionDays) {
        String sql = "delete from domain_event_record where record_time <= ?";
        LocalDateTime beforeDay = LocalDateTime.now().minusDays(retentionDays);
        int deleteCount = this.npJdbcTemplate.getJdbcTemplate().update(sql, beforeDay);
        log.debug("Clean domain events records, total clean count: {}", deleteCount);
    }
}
